123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665 |
- "use client";
- import { GameListRep } from "@/api/home";
- import { userInfoApi } from "@/api/login";
- import { Wallet } from "@/api/user";
- import { ChannelType, getWithDrawApi, WithDrawParams, WithDrawType } from "@/api/withdraw";
- import { clearWallet } from "@/app/[locale]/(navbar)/withdraw/actions";
- import Box from "@/components/Box";
- import ButtonOwn from "@/components/ButtonOwn";
- import Empty from "@/components/Empty";
- import MobileField from "@/components/Fields/MobileField";
- import TipsModal, { ModalProps } from "@/components/TipsModal";
- import useGame from "@/hooks/useGame";
- import { useSystemStore } from "@/stores/useSystemStore";
- import { useUserInfoStore } from "@/stores/useUserInfoStore";
- import { useWalletStore } from "@/stores/useWalletStore";
- import { isEmail } from "@/utils";
- import { flatPoint, percentage } from "@/utils/methods";
- import { ActionSheet, Button, Form, Input, ProgressBar, Toast } from "antd-mobile";
- import { FormInstance } from "antd-mobile/es/components/form";
- import { useTranslations } from "next-intl";
- import Link from "next/link";
- import { FC, useRef, useState } from "react";
- import { Swiper, SwiperSlide } from "swiper/react";
- import "./page.scss";
- interface Props {
- channels: WithDrawType[];
- wallet: Wallet;
- playlist?: GameListRep[];
- }
- export enum ChannelEnum {
- CPF = 1,
- Email,
- Phone,
- CNPJ,
- }
- type FieldValueType = {
- account_no: string;
- channel_id: (typeof ChannelEnum)[keyof typeof ChannelEnum];
- type: number;
- code_phone?: string;
- };
- interface MobileFieldProps {
- value?: FieldValueType;
- onChange?: (value: FieldValueType) => void;
- actions: Array<ChannelType & { text: string; key: number }>;
- }
- const PixField: FC<MobileFieldProps> = (props) => {
- const {
- actions,
- value = { account_no: "", channel_id: actions[0].id, type: actions[0].type },
- onChange,
- } = props;
- let [visible, setVisible] = useState(false);
- const t = useTranslations("WithdrawPage");
- let [prefix, setPrefix] = useState<ChannelType & { text: string; key: number }>(actions[0]);
- let [placeholder, setPlaceholder] = useState("000.000.000-00");
- const onAction = (item: any) => {
- setPrefix(item);
- onRealValueChange("");
- if (item.type === ChannelEnum.CPF) {
- setPlaceholder("000.000.000-00");
- return;
- }
- if (item.type === ChannelEnum.CNPJ) {
- setPlaceholder("00.000.000.0000-00");
- return;
- }
- if (item.type === ChannelEnum.Phone) {
- setPlaceholder("11 dígitos");
- return;
- }
- if (item.type === ChannelEnum.Email) {
- setPlaceholder("Email");
- return;
- }
- };
- const onRealValueChange = (value: string) => {
- console.log(`🚀🚀🚀🚀🚀-> in WithdrawWidget.tsx on 80`, value);
- // console.log('prefix', prefix)
- let account_no = value;
- if (prefix.type === 1) {
- account_no = value
- .replace(/[^0-9]/g, "")
- .replace(/[\-]/g, "")
- .slice(0, 11);
- // console.log('account_no', value.replace(/\D/g, ''))
- // account_no = account_no.slice(0,3)
- }
- if (onChange) {
- onChange({ account_no, channel_id: prefix.id, type: prefix.type });
- // console.log('value', props.value)
- }
- };
- const mobileChange = (values: any) => {
- if (onChange) {
- onChange({
- account_no: values.realValue,
- channel_id: prefix.id,
- type: prefix.type,
- code_phone: values.preValue,
- });
- }
- };
- return (
- <>
- <div className="flex">
- <div onClick={() => setVisible(true)} className={"mr-[0.1rem] flex flex-shrink-0"}>
- <span className={"mr-[0.1rem]"}>{prefix.text}</span>
- <span className="iconfont icon-xialaxuanze"></span>
- </div>
- {prefix.type === ChannelEnum.Phone ? (
- <MobileField
- value={{ preValue: "55", realValue: value.account_no }}
- onChange={mobileChange}
- />
- ) : (
- <Input
- name="secretKey"
- value={value.account_no}
- placeholder={placeholder}
- onChange={onRealValueChange}
- />
- )}
- </div>
- <ActionSheet
- extra=""
- cancelText={t("Cancelar")}
- visible={visible}
- actions={actions}
- style={{ background: "#fff" }}
- closeOnAction={true}
- getContainer={null}
- onAction={onAction}
- onClose={() => setVisible(false)}
- />
- </>
- );
- };
- const WithdrawWidget: FC<Props> = (props) => {
- const t = useTranslations();
- const { channels, wallet } = props;
- const { getGameUrl } = useGame();
- const isStrictMode = useSystemStore((state) => state.identity_verify.withdraw === 1);
- const score = useWalletStore((state) => state.score)!;
- // 彩金
- const withdrawRef = useRef<ModalProps>(null);
- const bounsModalRef = useRef<ModalProps>(null);
- // 积分
- const scoreRef = useRef<ModalProps>(null);
- // 未完成游戏
- const gameModelRef = useRef<ModalProps>(null);
- const game = useRef<GameListRep | null>(null);
- // 表单
- const formRef = useRef<FormInstance>(null);
- // 是否能提现
- const [activeWallet, setActiveWallet] = useState<WithDrawType>(channels[0]);
- const walletAction =
- activeWallet &&
- activeWallet.channels?.map((item) => ({
- text: ChannelEnum[item.type],
- key: item.id,
- ...item,
- }));
- const userInfo = useUserInfoStore((state) => state.userInfo);
- const initParams = {
- channel: "",
- amount: "",
- passport: userInfo.passport,
- user_name: userInfo.user_name,
- };
- const paramsTarget = useRef<WithDrawParams | null>(null);
- const AmountValidator = (rules: any, value: string) => {
- const num = +value;
- if (num > activeWallet.max_amount) {
- return Promise.reject(
- new Error(t("WithdrawPage.amountReg", { max: activeWallet.max_amount }))
- );
- }
- if (score && num > score) {
- return Promise.reject(new Error(t("WithdrawPage.amountMaxReg")));
- }
- return Promise.resolve();
- };
- const ChannelValidator = (rules: any, value: FieldValueType) => {
- if (!value.account_no) return Promise.reject(new Error(t("WithdrawPage.channel")));
- if (value.type === ChannelEnum.CPF) {
- return value.account_no.length !== 11
- ? Promise.reject(new Error(t("WithdrawPage.cpfReg")))
- : Promise.resolve();
- }
- if (value.type === ChannelEnum.CNPJ) {
- return value.account_no.length !== 14
- ? Promise.reject(new Error(t("WithdrawPage.cnpjReg")))
- : Promise.resolve();
- }
- if (value.type === ChannelEnum.Email) {
- return isEmail(value.account_no)
- ? Promise.resolve()
- : Promise.reject(new Error(t("WithdrawPage.EmailReg")));
- }
- if (value.type === ChannelEnum.Phone) {
- return value.account_no.length < 10
- ? Promise.reject(new Error(t("WithdrawPage.phoneReg")))
- : Promise.resolve();
- }
- return Promise.resolve();
- };
- const onFinish = async (value: any) => {
- const params = { ...value, ...value.channel, amount: +value.amount };
- // 如果是电话号码,拼接区号
- if (params.code_phone) {
- params.account_no = `${params.code_phone}${params.account_no}`;
- }
- delete params.channel;
- const { data } = await userInfoApi();
- // 如果有未完成游戏
- if (data.play_list && data.play_list.length > 0) {
- game.current = data.play_list[0];
- gameModelRef.current?.onOpen();
- return;
- }
- // 如果彩金 || 彩金打码量不为0
- if (
- flatPoint(wallet.target_point_rollover - wallet.current_point_rollover) > 0 ||
- (wallet.point || 0) > 0
- ) {
- paramsTarget.current = params;
- bounsModalRef.current?.onOpen();
- return;
- }
- extractHandler(params);
- };
- const extractHandler = async (params: WithDrawParams) => {
- const withResult = await getWithDrawApi(params).catch((error) => {
- Toast.show(t(`code.${error.data.code}`));
- });
- if (withResult && withResult.code === 200) {
- Toast.show(t("code.200"));
- }
- await clearWallet();
- };
- const goGame = () => {
- const current = game.current;
- getGameUrl(current!, { id: current?.id + "" });
- };
- if (!activeWallet) return <Empty />;
- return (
- <>
- <Box className={"custom-form"}>
- <div className="withdraw-box">
- <div className="img-box">
- <img
- className={"h-[100%] w-[100%] object-cover"}
- src={activeWallet.icon}
- alt={activeWallet.name}
- width={160}
- height={40}
- />
- </div>
- {/*<div className={"mb-[0.1rem] flex flex-wrap gap-[0.0347rem]"}>*/}
- {/* {channels.map((item) => {*/}
- {/* return (*/}
- {/* <Fragment key={item.id}>*/}
- {/* <p*/}
- {/* className={`btn-box ${activeWallet.id === item.id ? "active" : ""}`}*/}
- {/* onClick={() => {*/}
- {/* formRef.current?.resetFields();*/}
- {/* setActiveWallet(item);*/}
- {/* }}*/}
- {/* >*/}
- {/* {item.name}*/}
- {/* </p>*/}
- {/* </Fragment>*/}
- {/* );*/}
- {/* })}*/}
- {/*</div>*/}
- <Swiper slidesPerView={"auto"} className={"mb-[0.1rem]"} centeredSlidesBounds>
- {channels?.map((item, index) => (
- <SwiperSlide key={item.id} className={"max-w-fit"}>
- <p
- className={`btn-box truncate ${activeWallet.id === item.id ? "active" : ""}`}
- onClick={() => {
- formRef.current?.resetFields();
- setActiveWallet(item);
- }}
- >
- {item.name}
- </p>
- </SwiperSlide>
- ))}
- </Swiper>
- <h1>{t("WithdrawPage.Certifique")}</h1>
- <p className={"text-[0.1rem] text-[#3bc117]"}>{t("WithdrawPage.keyTips")}</p>
- <ul className={"ml-[0.11rem] list-decimal text-[0.1rem]"}>
- <li>
- {t("WithdrawPage.rulesRange", {
- min: activeWallet.min_amount,
- max: activeWallet.max_amount,
- })}
- </li>
- <li>
- {t("WithdrawPage.rulesToll", {
- toll: activeWallet.fee_rate,
- })}
- </li>
- </ul>
- {/* form */}
- <Form
- style={{
- "--border-bottom": "none",
- "--border-top": "none",
- "--border-inner": "none",
- }}
- ref={formRef}
- onFinish={onFinish}
- initialValues={initParams}
- disabled={!activeWallet.channels}
- hasFeedback={!!activeWallet.channels}
- className={"mt-[0.1rem]"}
- footer={<ButtonOwn active>{t("WithdrawPage.Saque")}</ButtonOwn>}
- >
- {isStrictMode ? (
- <>
- <Form.Item
- name="user_name"
- label=""
- rules={[
- { required: true, message: t("WithdrawPage.usernameReg") },
- ]}
- >
- <Input placeholder={t("WithdrawPage.username")} />
- </Form.Item>
- <Form.Item
- name="passport"
- label=""
- rules={[
- {
- required: true,
- message: t("WithdrawPage.cpfReg"),
- min: 6,
- max: 20,
- },
- ]}
- >
- <Input
- placeholder={t("WithdrawPage.cpf")}
- maxLength={20}
- type={"text"}
- />
- </Form.Item>
- </>
- ) : null}
- <p className={"my-[0.1rem]"}>{t("WithdrawPage.Tipo")}</p>
- {activeWallet.channels?.length && (
- <Form.Item
- name="channel"
- label=""
- rules={[{ validator: ChannelValidator }]}
- >
- <PixField actions={walletAction || []} />
- </Form.Item>
- )}
- <h1>{t("WithdrawPage.Vincule")}</h1>
- <p className={"my-[0.1rem]"}>{t("WithdrawPage.Montante")} (BRL):</p>
- <Form.Item
- name="amount"
- label=""
- rules={[
- { required: true, message: t("WithdrawPage.amount") },
- {
- type: "number",
- validator: AmountValidator,
- },
- ]}
- >
- <Input
- placeholder={`Mín. ${activeWallet.min_amount || 0}`}
- type={"number"}
- min={activeWallet.min_amount}
- />
- </Form.Item>
- <ul className="ul-box">
- <li>
- {t("WithdrawPage.SaqueDisponivel")}{" "}
- <span className="tip">
- {/* 如果当前现金打码量等于当前目标打码量 则 可以提现, 如果当前打码量=== 100% 则可以提现 */}
- {flatPoint(
- wallet.target_score_rollover - wallet.current_score_rollover
- ) === 0 ||
- percentage(
- wallet.current_score_rollover,
- wallet.target_score_rollover
- ) >= 100
- ? wallet.score
- : 0}
- BRL
- </span>
- <span
- className="iconfont icon-iconhelp"
- onClick={() => scoreRef.current?.onOpen()}
- ></span>
- </li>
- <li>
- {t("WithdrawPage.Valor")}
- <span className="tip">
- {flatPoint(
- wallet.target_score_rollover - wallet.current_score_rollover
- ) === 0 ||
- percentage(
- wallet.current_score_rollover,
- wallet.target_score_rollover
- ) >= 100
- ? flatPoint((wallet.score || 0) + wallet.point)
- : 0}
- BRL
- </span>
- <span
- className="iconfont icon-iconhelp"
- onClick={() => withdrawRef.current?.onOpen()}
- ></span>
- </li>
- <li>
- {t("WithdrawPage.Para")},{" "}
- <Link href="/" className="toHome router-link-active" replace>
- {t("WithdrawPage.Aposte")}
- </Link>
- </li>
- </ul>
- </Form>
- </div>
- </Box>
- {/*本金*/}
- <TipsModal
- title={
- <div className={"flex items-center"}>
- <i
- className={"iconfont icon-liwuhuodong mr-[0.0694rem] text-[0.2778rem]"}
- ></i>
- SACAR
- {t("WithdrawPage.scoreTitle")}
- </div>
- }
- ref={scoreRef}
- >
- <ul>
- <li className={"mb-[0.0694rem]"}>
- <span>{t("WithdrawPage.scoreTips")}</span>
- <span>{wallet.score}</span>
- </li>
- <li>
- <div className={"flex items-center"}>
- <ProgressBar
- percent={percentage(
- wallet.current_score_rollover,
- wallet.target_score_rollover
- )}
- className={"mr-[0.0694rem] flex-1"}
- style={{
- "--fill-color": "#fb8b05",
- "--track-width": "0.0694rem",
- }}
- />
- <span>
- {percentage(
- wallet.current_score_rollover,
- wallet.target_score_rollover
- )}
- %
- </span>
- </div>
- <div>
- <span>{t("WithdrawPage.pointBet")}</span>
- <span>
- {flatPoint(
- wallet.target_score_rollover - wallet.current_score_rollover
- )}
- </span>
- </div>
- </li>
- </ul>
- </TipsModal>
- {/*彩金*/}
- <TipsModal
- title={
- <div className={"flex items-center"}>
- <i
- className={"iconfont icon-liwuhuodong mr-[0.0694rem] text-[0.2778rem]"}
- ></i>
- {t("WithdrawPage.pointTitle")}
- </div>
- }
- ref={withdrawRef}
- >
- <ul>
- <li className={"mb-[0.0694rem]"}>
- <span>{t("WithdrawPage.pointTips")}</span>
- <span>{wallet.point}</span>
- </li>
- <li>
- <div className={"flex items-center"}>
- <ProgressBar
- percent={percentage(
- wallet.current_point_rollover,
- wallet.target_point_rollover
- )}
- className={"mr-[0.0694rem] flex-1"}
- style={{
- "--fill-color": "#fb8b05",
- "--track-width": "0.0694rem",
- }}
- />
- <span>
- {percentage(
- wallet.current_point_rollover,
- wallet.target_point_rollover
- )}
- %
- </span>
- </div>
- <div>
- <span>{t("WithdrawPage.pointBet")}</span>
- <span>
- {flatPoint(
- wallet.target_point_rollover - wallet.current_point_rollover
- )}
- </span>
- </div>
- </li>
- </ul>
- </TipsModal>
- {/*含有彩金提现拦截*/}
- <TipsModal
- title={
- <div className={"text-left text-[0.12rem] font-medium text-[#666]"}>
- Retirar bem sucedido, seu dinheiro de prémio será limpo. Você tem certeza?
- </div>
- }
- ref={bounsModalRef}
- >
- <ul>
- <li className={"mb-[0.0694rem]"}>
- <span>{t("WithdrawPage.pointTips")}</span>
- <span>{wallet.point}</span>
- </li>
- <li>
- <div className={"flex items-center"}>
- <ProgressBar
- percent={percentage(
- wallet.current_point_rollover,
- wallet.target_point_rollover
- )}
- className={"mr-[0.0694rem] flex-1"}
- style={{
- "--fill-color": "#fb8b05",
- "--track-width": "0.0694rem",
- }}
- />
- <span>
- {percentage(
- wallet.current_point_rollover,
- wallet.target_point_rollover
- )}
- %
- </span>
- </div>
- <div>
- <span>{t("WithdrawPage.pointBet")}</span>
- <span>
- {flatPoint(
- wallet.target_point_rollover - wallet.current_point_rollover
- )}
- </span>
- </div>
- <div className={"mt-[20px] flex justify-around"}>
- <Button
- color={"default"}
- fill={"none"}
- style={{
- "--text-color": "var(--primary-color)",
- }}
- onClick={() => {
- bounsModalRef.current?.onClose();
- }}
- >
- cancelar
- </Button>
- <Button
- color={"primary"}
- className={"ml-[30px]"}
- style={{
- "--background-color": "var(--primary-color)",
- "--border-color": "var(--primary-color)",
- }}
- onClick={() => {
- // 关闭彩金弹窗
- bounsModalRef.current?.onClose();
- extractHandler(paramsTarget.current!);
- }}
- >
- confirmação
- </Button>
- </div>
- </li>
- </ul>
- </TipsModal>
- {/* 提现拦截 */}
- <TipsModal title={"Tips"} ref={gameModelRef}>
- <p className={"text-left text-[0.12rem] font-medium text-[#666]"}>
- Atualmente, existem jogos de bônus inacabados que não podem iniciar saques.
- </p>
- <div className={"mt-[0.0694rem] flex justify-center"}>
- <Button
- color={"primary"}
- className={"mx-auto"}
- style={{
- "--background-color": "var(--primary-color)",
- "--border-color": "var(--primary-color)",
- }}
- onClick={goGame}
- >
- para jogos
- </Button>
- </div>
- </TipsModal>
- </>
- );
- };
- export default WithdrawWidget;
|